/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "解算器.h"

#include "节点/插座/C_数值插座.h"
#include "节点/插座/C_单值矢量插座.h"
#include "节点/插座/C_物理物体插座.h"
#include "节点/插座/通用插座.h"

#include <节点/插座/list/list数值插座.h>
#include <节点/插座/list/list物体插座.h>
#include <节点/插座/list/list物理物体插座.h>
#include <节点/插座/list/list矢量插座.h>


#include <节点/节点树.h>
#include <Range.h>


#include <面/几何模型生成.h>
//#include <物理/物理.h>
#include <Context/当前默认操作数据.h>

#include "异步解算/物理异步解算.h"

#include <NvFleX封装.h>
#include <场景/场景.h>

#define DEF_物理计算帧未初始化 -1



#pragma comment(lib,"./NvFleX封装.lib")



static S_FLIP可视预览材质*	gFLIP调试材质 = 0;
static S_PBF可视预览材质* gPBF调试材质 = 0;
static S_PBF可视预览材质*		gPBF材质飞溅粒子 = 0;
static S_体素可视网格预览材质*	gPBF体素可视 = 0;
//static S_线单色材质* g_FLIP边框材质 = 0;
static S_线基本光照材质*	g_域边框材质 = 0;



static S_物体*				g_域大小可视物体 = nullptr;
static S_物体*				g_体素可视物体 = nullptr;













struct S_NvFleX : public S_Physics {
	uint64			m_NvFleX_Key;
	S_FlexParams	m_解算参数;
	uint8			m_GPU;

	std::vector<S_物理体*>	m_刚体;
	std::vector<S_物理体*>	m_物理体;


	S_NvFleX() {
		m_GPU = 0;
		m_NvFleX_Key = f_NvFlex_初始化参数(0);
		m_IdType = E_物理引擎::E_物理引擎_FleX;

		m_解算参数.m_飞溅粒子数量 = 0;
		m_解算参数.m_粒子数量 = 0;
	}
	~S_NvFleX() {
		f_NvFlex_释放(m_NvFleX_Key);
	}
	void	f_Update() {
		f_NvFleX_更新(m_NvFleX_Key, m_解算参数);
	}

	float32	f_getR() {
		return 0.1;
	}
	uint64	f_getID() {
		return m_NvFleX_Key;
	}
	void	f_get粒子坐标(uint32 id, std::vector<vec3>& particle) {
		uvec2 r = f_Phy_get粒子区间(m_物理体[id]);
		f_NvFleX_取区间坐标数据(m_NvFleX_Key, r, particle);
	}
	void	f_get粒子速度(uint32 id, std::vector<float32>& speed) {
		uvec2 r = f_Phy_get粒子区间(m_物理体[id]);
	}
	void	f_get粒子大小(uint32 id, std::vector<float32>& size) {
		uvec2 r = f_Phy_get粒子区间(m_物理体[id]);

		uint32 offset = size.size();
		size.resize(offset + (r.y - r.x));
		for (uint32 i = r.x; i < r.y; ++i, ++offset) {
			size[offset] = m_解算参数.radius;
		}
	}

	void f_selectGPU(uint8 gpuID)
	{
		if (m_GPU != gpuID) {
			if (m_NvFleX_Key) {
				f_NvFlex_释放(m_NvFleX_Key);
			}

			m_GPU = gpuID;
			m_NvFleX_Key = f_NvFlex_初始化参数(m_GPU);
		}
	}

	void f_更新物体刚体变换(const std::vector<vec4>& q, const std::vector<vec3>& loc) {
		uint32 num = m_刚体.size();
		auto* body = m_刚体.data();
		auto* 四元数 = q.data();
		auto* 位置 = loc.data();
		for (uint32 i = 0; i < num; ++i) {
			vec3 rotA = ((S_物体*)(body[i]->m_绑定物体))->f_get旋转();
			
			auto mat = f_从变换构建矩阵(位置[i], {}, { 1,1,1 });
			mat *= f_mat3x3_4X4(f_mat3x3_quat(四元数[i]));
			mat *= f_mat3x3_4X4(f_mat3x3_quat(((S_物体*)(body[i]->m_绑定物体))->f_get四元数()));

			((S_物体*)(body[i]->m_绑定物体))->f_set矩阵((Mat44f*)&mat);
		}
	}

	void f_重置所有() {
		uint32 构建ID = 0;
		uint64 offset = 0;

		f_NvFleX_重置begin(m_NvFleX_Key, m_解算参数.m_飞溅粒子数量);

		for (auto& e : m_物理体) {
			uvec2 区间 = {};
			S_体素* vo = f_Phy_get发射源体素(e);
			if (!vo) continue;

			assert(vo);
			uint64 num = 0;
			//std::vector<vec3> 坐标 = vo->m_坐标;

			e->m_ID = 构建ID;
			++构建ID;

			switch (e->m_Type)
			{
			case E_物理体类型::E_物理体_流体: {
				num = vo->m_坐标.size();
				std::vector<float32> 质量 = f_range(num, 0.5);
				区间 = f_NvFleX_添加流体(f_getID(), vo->m_坐标.data(), 质量.data(), 0, num, true);
				//是否激活 = true;
				break;
			}
			case E_物理体类型::E_物理体_流入: {
				num = f_Phy_get发射总数(e);
				if (num) {
					f_Phy_重置发射源(e);
					std::vector<vec3> 坐标 = f_range(num, vec3{ 0,0,0 });
					std::vector<float32> 质量 = f_range(num, 0.5);

					区间 = f_NvFleX_添加流体(f_getID(), 坐标.data(), 质量.data(), 0, num, false);
					//是否激活 = false;
				}
				break;
			}
			case E_物理体类型::E_物理体_刚体: {
				num = vo->m_坐标.size();
				if (num) {
					std::vector<float32> 质量 = f_range(num, 0.5);

					区间 = f_NvFleX_添加刚体(f_getID(), vo->m_坐标.data(), 质量.data(), vo->m_法线.data(), 0, num, e->m_ID, 1.0);
					m_刚体.push_back(e);
				}
				break;
			}
			default:
				continue;
				break;
			}

			f_Phy_set粒子区间(e, { 区间.x, 区间.y - 区间.x }, offset);
			offset += 区间.y;
		}
		//m_步进ID = 0;
		m_解算参数.m_粒子数量 = offset;
		f_NvFleX_重置end(m_NvFleX_Key);
	}

	void f_重置() {
		uvec2 区间 = {};
		
		f_NvFleX_重置begin(m_NvFleX_Key, 0, false);


		for (auto& e : m_物理体) {
			S_体素* vo = f_Phy_get发射源体素(e);
			uint64 num = 0;

			switch (e->m_Type)
			{
			case E_物理体类型::E_物理体_流体: {
				num = vo->m_坐标.size();
				uvec2 区间 = f_Phy_get粒子区间(e);
				std::vector<float32> 质量 = f_range(num, 0.5);
				f_NvFleX_set流体(f_getID(), vo->m_坐标.data(), 质量.data(), 0, 区间, true);
				//是否激活 = true;
				break;
			}
			case E_物理体类型::E_物理体_流入: {
				num = f_Phy_get发射总数(e);
				if (num) {
					f_Phy_重置发射源(e);
					std::vector<vec3> 坐标 = f_range(num, vec3{ 0,0,0 });
					std::vector<float32> 质量 = f_range(num, 0.5);
					uvec2 区间 = f_Phy_get粒子区间(e);
					f_NvFleX_set流体(f_getID(), 坐标.data(), 质量.data(), 0, 区间, false);
					//是否激活 = false;
				}
				break;
			}
			case E_物理体类型::E_物理体_刚体: {
				num = vo->m_坐标.size();
				if (num) {
					std::vector<float32> 质量 = f_range(num, 0.5);

					f_NvFleX_添加刚体(f_getID(), vo->m_坐标.data(), 质量.data(), vo->m_法线.data(), 0, num, e->m_ID, 1.0);
					m_刚体.push_back(e);
				}
				break;
			}
			default:
				continue;
				break;
			}
		}
		
		f_NvFleX_重置end(m_NvFleX_Key, false);
	}

	void f_Save(FILE* f) {

	}
	void f_Load(FILE* f) {
		
	}
};





static S_物体* f_域范围可视物体(S_设备环境& ctx) {
	if (!g_域边框材质) {
		g_域边框材质 = new S_线基本光照材质(ctx);
	}


	if (g_域大小可视物体 == nullptr) {
		g_域大小可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
		f_ob_set数据槽数量(g_域大小可视物体, 1);

		auto* mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
		g_域大小可视物体->f_setData(mesh, 0);

		f_ob_set材质(g_域大小可视物体, g_域边框材质, 0);
		g_域边框材质->f_set颜色({ 100, 255, 255, 255 });




		DEF_3Fs 顶点;
		DEF_3Fs 法线;
		DEF_2Fs UV;
		DEF_Is 索引;
		
		f_graph_构建立方体({ 1,1,1 }, { 1,1,1 }, 顶点, 法线, UV, 索引);


		std::vector<S_VN> vnData;
		f_surface_数组合并(vnData, 顶点, 法线);
		f_surface_fill顶点数据(mesh, vnData);
		f_填充索引数据(mesh, 索引);



		//g_体素可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
		g_域大小可视物体->m_Name = L"域范围可视物体";
	}

	return g_域大小可视物体;
}







C_FLIP解算器节点::C_FLIP解算器节点(E_物理引擎 解算器类型, S_设备环境& ctx) : C_节点基类("FLIP解算器节点") {
	m_Name = L"FLIP";
	m_GPU环境 = ctx;
	m_解算器类型 = 解算器类型;
	C_插座基类* socket;
	
	DEF_创建UI32插座_I(L"域分辨率");
	DEF_创建F32插座_v1_I(L"域边界大小");
	DEF_创建F32插座_v1_I(L"步进时间");

	DEF_创建物理引擎插座_O(L"物理引擎");


	DEF_UI32插座数据(f_get输入插座(1), 0) = 32;
	DEF_F32插座数据(f_get输入插座(2)) = 1.0f;
	DEF_F32插座数据(f_get输入插座(3)) = 1.0f / 60.0f;





	f_域范围可视物体(ctx);
	

}

C_FLIP解算器节点::~C_FLIP解算器节点() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1), 0);

	if (m_Physics) {
		f_phy_销毁物理解算器(m_Physics);
	}

	f_get输出插座(1)->f_setData((S_Physics*)nullptr, 0);
}

bool C_FLIP解算器节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1), 0);
	S_Mesh* mesh = 0;



	if (!m_Physics) {
		m_Physics = f_phy_创建创建解算器(m_解算器类型, { 10, 10 , 10 });
		f_get输出插座(1)->f_setData(m_Physics, 0);

		f_NodeCtx_get默认场景()->f_add物体({ g_域大小可视物体 }, E_场景物体容器类型::e_集合);
	}


	
	uint32 域分辨率 = DEF_UI32插座数据(f_get输入插座(1), 0);
	float32 域大小 = DEF_F32插座数据(f_get输入插座(2));

	if (域分辨率 <= 0) 域分辨率 = 1;
	if (域分辨率 > 512) 域分辨率 = 512;


	S_域区& dom = *f_Phy_get域属性(m_Physics);
	if (dom.m_单元属性.m_分辨率.x != 域分辨率) {
		dom.m_单元属性.m_分辨率.x = 域分辨率;
		dom.m_单元属性.m_分辨率.y = 域分辨率;
		dom.m_单元属性.m_分辨率.z = 域分辨率;


		g_域大小可视物体->f_set缩放(dom.m_单元属性.m_分辨率.x, dom.m_单元属性.m_分辨率.y, dom.m_单元属性.m_分辨率.z);
	}


	dom.m_单元属性.m_世界大小.x = 域大小;
	dom.m_单元属性.m_世界大小.y = 域大小;
	dom.m_单元属性.m_世界大小.z = 域大小;


	const uint32 old分辨率 = f_phy_get解算器域分辨率(m_Physics);
	if (old分辨率 != 域分辨率) {
		
		f_Phy_set解算器域分辨率(m_Physics, m_解算器类型, 域分辨率, { 域大小 ,域大小, 域大小}, 0.1);
		
	}
	else {
		//mesh = f_ob_from物体Mesh(m_数据可视物体);
	}



	/*if (域分辨率) {
		E_序列map v = mesh->f_map顶点();

		//填充GPU可视数据
		f_Phy_取流体调试数据(m_Physics, (S_FLIP可视数据*)v.point);

		mesh->f_unmap顶点();
	}*/
	return false;
}



void C_FLIP解算器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_FLIP解算器节点::f_写入(FILE* f) {
	
	C_节点基类::f_写入(f);
}


C_节点基类* f_node_加载FLIP解算器节点(S_设备环境& ctx, FILE* f) {
	E_物理引擎 解算器类型;
	fread(&解算器类型, sizeof(uint32), 1, f);

	C_FLIP解算器节点* node = new C_FLIP解算器节点(解算器类型, ctx);
	return node;
}

void f_node_保存FLIP解算器节点(C_节点基类* n, FILE* f) {
	C_FLIP解算器节点* node = dynamic_cast<C_FLIP解算器节点*>(n);

	fwrite(&node->m_解算器类型, sizeof(uint32), 1, f);

}











void fp_解算器切换(S_Props& prop) {

}

C_PBF解算器节点::C_PBF解算器节点(S_设备环境& ctx) : C_节点基类("PBF解算器节点") {
	m_Name = L"PBF";
	//m_GPU环境 = ctx;
	m_解算器类型 = E_物理引擎::E_物理引擎_PBF;
	m_记录物理体状态 = DEF_物理计算帧未初始化;

	C_插座基类* socket;
	DEF_创建F32插座_v1_I(L"步进时间");
	DEF_创建F32插座_v1_I(L"解算精度");
	//DEF_创建F32插座_I(L"碰撞单元大小");
	DEF_创建物理体_1D插座_I(L"物理体");
	

	DEF_创建物理引擎插座_O(L"物理引擎");


	f_域范围可视物体(ctx);
	DEF_F32插座数据(f_get输入插座(1)) = 1.0f/60.0f;


	m_物理引擎类型 = f_alloc_EnumProp(nullptr, { {L"FleX", ""}, {L"内部", ""}, {L"SPlisHSPlasH", ""} }, L"解算器", 0, fp_解算器切换);
	m_物理引擎类型.m_私有 = true;

	m_GPU = f_alloc_EnumProp(nullptr, { {L"GPU:0", ""}, {L"GPU:1", ""}, {L"GPU:2", ""} }, L"GPU ID", 0, fp_解算器切换);
	m_GPU.m_私有 = true;

	m_飞溅粒子数量 = f_alloc_UI32Prop(nullptr, L"飞溅粒子数量");
	m_飞溅粒子数量.m_私有 = true;
	f_prop_UI32(m_飞溅粒子数量) = 1000;
}

C_PBF解算器节点::~C_PBF解算器节点() {
	f_release_EnumProp(m_物理引擎类型);
}

bool C_PBF解算器节点::f_update() {
	
	float32 r = DEF_F32插座数据(f_get输入插座(2));

	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	S_Mesh* mesh = 0;


	auto& phytype = f_prop_enum(m_物理引擎类型);
	if (!m_Physics) {
		switch (phytype) {
		case 0:
			m_Physics = new S_NvFleX();
			break;
		case 1:
			m_Physics = f_phy_创建创建解算器(m_解算器类型, { 10, 10 , 10 });
			m_Physics->m_IdType = E_物理引擎::E_物理引擎_PBF;
			break;
		case 2:
			break;
		}
		
		m_Physics->m_Key = m_记录物理体状态;
		f_get输出插座(1)->f_setData(m_Physics, 0);
		//f_NodeCtx_get默认场景()->f_add物体(g_域大小可视物体, E_场景物体容器类型::e_集合);
	}
	

	switch (phytype) {
	case 0: {
		uint32 LinkNum = f_get输入插座(3)->f_getLinkNum();
		uint32 构建ID = 0;
		uint64 offset = 0;


		S_NvFleX* flex = static_cast<S_NvFleX*>(m_Physics);
		flex->f_selectGPU(f_prop_enum(m_GPU));

		
		if (f_get输入插座(3)->m_有新数据 || flex->m_解算参数.m_飞溅粒子数量 != f_prop_UI32(m_飞溅粒子数量)) {
			flex->m_刚体.clear();
			flex->m_物理体.clear();
			flex->m_解算参数.m_飞溅粒子数量 = f_prop_UI32(m_飞溅粒子数量);
			//f_NvFleX_重置begin(flex->m_NvFleX_Key, flex->m_解算参数.m_飞溅粒子数量);
			for (uint32 i = 0; i < LinkNum; ++i) {
				auto& in物理体 = *DEF_物理体插座_1D数据(f_get输入插座(3), i);
				flex->m_物理体.insert(flex->m_物理体.end(), in物理体.begin(), in物理体.end());
			}

			
			if (m_记录物理体状态 != DEF_物理计算帧未初始化) {
				flex->m_Key = m_记录物理体状态;
				m_记录物理体状态 = DEF_物理计算帧未初始化;
			}
			else {
				flex->m_Key = clock() + flex->m_物理体.size();
				
			}
			
			flex->m_是否初始化 = true;
			//flex->m_Key = f_strVal_整数转16进制字符串((uint8*)&key, 8);
			//key = flex->m_物理体.size();
			//flex->m_Key += f_strVal_整数转16进制字符串((uint8*)&key, 2);
		}
		else {
			float32 解算时间 = DEF_F32插座数据(f_get输入插座(1));
			
			flex->f_重置();
		}

		break;
	}
	case 1: {
		/*vec3 offset = vec_取反(dimSize);
		f_Phy_set解算器域(m_Physics, dimSize * 2, offset, r);
		f_Phy_set流体飞溅粒子数量(m_Physics, f_prop_UI32(m_飞溅粒子数量));
		auto& meshs = *DEF_网格插座_1D数据(f_get输入插座(6), 0);
		for (auto& mesh : meshs) {
			std::vector<vec3> verts;
			f_surface_get顶点数据(mesh, verts);
			std::vector<uvec3> indexs;
			f_surface_get索引数据(mesh, indexs);
			f_Phy_add静态碰撞网格(m_Physics, verts, indexs);
		}
		f_Phy_构建静态网格碰撞划分(m_Physics, 最小网格单元大小);*/
		break;
	}
	case 2:
		break;
	}

	return false;
}


void C_PBF解算器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_物理引擎类型, f);
	f_prop_Load(m_GPU, f);
	f_prop_Load(m_飞溅粒子数量, f);

	fread(&m_记录物理体状态, sizeof(uint64), 1, f);
	
}

void C_PBF解算器节点::f_写入(FILE* f) {
	//fwrite(&m_解算器类型, sizeof(uint32), 1, f);
	C_节点基类::f_写入(f);

	f_prop_Save(m_物理引擎类型, f);
	f_prop_Save(m_GPU, f);
	f_prop_Save(m_飞溅粒子数量, f);

	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	if (m_Physics) {
		fwrite(&m_Physics->m_Key, sizeof(uint64), 1, f);
	}
	else {
		fwrite(&m_记录物理体状态, sizeof(uint64), 1, f);
	}
	
}

C_节点基类* f_node_加载PBF解算器节点(S_设备环境& ctx, FILE* f) {
	//fread(&解算器类型, sizeof(uint32), 1, f);
	C_PBF解算器节点* node = new C_PBF解算器节点(ctx);
	auto& phytype = f_prop_enum(node->m_物理引擎类型);
	uint32 解算器类型;
	fread(&解算器类型, sizeof(uint32), 1, f);
	phytype = 解算器类型;

	return node;
}

void f_node_保存PBF解算器节点(C_节点基类* n, FILE* f) {
	C_PBF解算器节点* node = dynamic_cast<C_PBF解算器节点*>(n);
	auto& phytype = f_prop_enum(node->m_物理引擎类型);
	uint32 解算器类型 = f_prop_enum(node->m_物理引擎类型);
	fwrite(&解算器类型, sizeof(uint32), 1, f);
	
}




C_物理引擎节点::C_物理引擎节点(S_设备环境& ctx) : C_节点基类(DEF_物理引擎节点) {
	m_Name = L"PBF";
	//m_GPU环境 = ctx;
	m_解算器类型 = E_物理引擎::E_物理引擎_PBF;
	m_记录物理体状态 = DEF_物理计算帧未初始化;

	C_插座基类* socket;
	DEF_创建F32插座_v1_I(L"步进时间");
	DEF_创建F32插座_v1_I(L"解算精度");
	DEF_创建物理体_1D插座_I(L"物理体");


	DEF_创建物理引擎插座_O(L"物理引擎");

	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	m_物理引擎类型.m_私有 = true;

	m_模型读写路径 = f_alloc_PathProp(nullptr, L"模型读写路径");
	m_模型读写路径.m_私有 = true;

	
}

C_物理引擎节点::~C_物理引擎节点() {

}

bool C_物理引擎节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	if (m_Physics) {
		if (m_Physics->m_IdType != f_prop_enum(m_物理引擎类型)) {
			f_phy_销毁物理解算器(m_Physics);
			goto To_物理引擎创建;
		}
	}
	else {
		To_物理引擎创建:
		
		m_Physics = f_phy_创建创建解算器(E_物理引擎(f_prop_enum(m_物理引擎类型)), {});
		f_get输出插座(1)->f_setData(m_Physics);
	}

	

	std::vector<S_物理体*> 物理体;
	uint32 body_num = f_get输入插座(3)->f_getLinkNum();

	switch (m_Physics->m_IdType)
	{
	case E_物理引擎::E_物理引擎_Mujoco: {
		
		for (uint32 i = 0; i < body_num; ++i) {
			auto& bodys = *DEF_物理体插座_1D数据(f_get输入插座(3), i);

			std::string 物理体类型;
			std::string 大小;
			for (auto& body : bodys) {
				m_Physics->m_XML += body->m_XML;

				switch (body->m_Type) {
				case E_物理体类型::E_物理体_刚体:
					break;
				case E_物理体类型::E_物理体_布料:
					break;
				case E_物理体类型::E_物理体_柔体:
					break;
				}

				物理体.emplace_back(body);
			}
		}

		auto path = f_prop_Path(m_模型读写路径).string();
		//f_Phy_添加物理体(m_Physics, 物理体);
		f_phy_重置(m_Physics, path);
		
		break;
	}

	case E_物理引擎::E_物理引擎_Bullet: {
		for (uint32 i = 0; i < body_num; ++i) {
			auto& bodys = *DEF_物理体插座_1D数据(f_get输入插座(3), i);

			for (auto& body : bodys) {
				物理体.emplace_back(body);
			}
		}

		f_Phy_添加物理体(m_Physics, 物理体);
		f_phy_重置(m_Physics);
		break;
	}
	default:
		break;
	}


	
	
	
	return false;
}

void C_物理引擎节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_物理引擎类型, f);
	f_prop_Load(m_模型读写路径, f);
	f_prop_Load(m_GPU, f);
}

void C_物理引擎节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_物理引擎类型, f);
	f_prop_Save(m_模型读写路径, f);
	f_prop_Save(m_GPU, f);
}

C_节点基类* f_node_加载物理引擎节点(S_设备环境& ctx, FILE* f) {
	C_物理引擎节点* node = new C_物理引擎节点(ctx);
	return node;
}

void f_node_保存物理引擎节点(C_节点基类* n, FILE* f) {
	C_物理引擎节点* node = dynamic_cast<C_物理引擎节点*>(n);
}






C_PBF粒子容器节点::C_PBF粒子容器节点(S_设备环境& ctx) : C_节点基类("PBF粒子容器节点") {

}

C_PBF粒子容器节点::~C_PBF粒子容器节点() {

}

bool C_PBF粒子容器节点::f_update() {
	return false;
}



C_节点基类* f_node_加载PBF粒子容器节点(S_设备环境& ctx, FILE* f) {
	C_PBF粒子容器节点* node = new C_PBF粒子容器节点(ctx);
	//fread(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	return node;
}

void f_node_保存PBF粒子容器节点(C_节点基类* n, FILE* f) {
	C_PBF粒子容器节点* node = dynamic_cast<C_PBF粒子容器节点*>(n);
	//fwrite(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
}


C_节点基类* f_node_加载PBF更新邻接信息节点(S_设备环境& ctx, FILE* f)
{
	return nullptr;
}

void f_node_保存PBF更新邻接信息节点(C_节点基类* n, FILE* f)
{

}



















C_解算器更新节点::C_解算器更新节点(S_设备环境& ctx) : C_节点基类("解算器更新节点") {
	m_Name = L"解算器更新";
	m_Ctx = ctx;
	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
	m_显示域体素 = true;
	m_是否完成计算 = 0;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建F32插座_v1_I(L"帧时间");
	//DEF_创建引用插座_I(L"功能");


	DEF_创建物理引擎插座_O(L"物理引擎");


	float32 步进时间 = 0.0;
	f_get输入插座(2)->f_setData(&步进时间);




	if (gFLIP调试材质 == nullptr) {
		gFLIP调试材质 = new S_FLIP可视预览材质(ctx);
	}
	if (gPBF调试材质 == nullptr) {
		gPBF调试材质 = new S_PBF可视预览材质(ctx);
		gPBF材质飞溅粒子 = new S_PBF可视预览材质(ctx);
		gPBF体素可视 = new S_体素可视网格预览材质(ctx);

		gPBF材质飞溅粒子->f_set颜色({ 0.8f, 0.8f, 0.8f, 1.0f });
	}

	

	m_上一次可视数据分辨率 = 0;
	m_数据可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	m_飞溅可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	m_数据可视物体->m_Name = L"物理流体可视物体";
	f_ob_set数据槽数量(m_数据可视物体, 2);
	f_ob_set数据槽数量(m_飞溅可视物体, 1);
	

	auto* mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
	auto* 体素网格 = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
	m_数据可视物体->f_setData(mesh, 0);
	m_数据可视物体->f_setData(体素网格, 1);
	f_ob_set材质(m_数据可视物体, gFLIP调试材质, 0);
	f_ob_set材质(m_数据可视物体, gPBF体素可视, 1);
	f_ob_set物体数据可视(m_数据可视物体, 1, false);

	mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
	m_飞溅可视物体->f_setData(mesh, 0);
	f_ob_set材质(m_飞溅可视物体, gPBF材质飞溅粒子, 0);


	m_肌腱可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	f_ob_set数据槽数量(m_肌腱可视物体, 1);
	auto* 肌腱网格 = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
	f_ob_set数据(m_肌腱可视物体, 肌腱网格);
	f_ob_set材质(m_肌腱可视物体, gPBF材质飞溅粒子, 0);


	f_NodeCtx_get默认场景()->f_add物体({ m_数据可视物体 }, E_场景物体容器类型::e_集合);
	f_NodeCtx_get默认场景()->f_add物体({ m_飞溅可视物体 }, E_场景物体容器类型::e_集合);
	f_NodeCtx_get默认场景()->f_add物体({ m_肌腱可视物体 }, E_场景物体容器类型::e_集合);


	m_粒子是否可视 = f_alloc_BoolProp(&m_数据可视物体->m_渲染, L"粒子可视");
	m_粒子是否可视.m_私有 = true;

	m_是否多线程 = f_alloc_BoolProp(nullptr, L"多线程");
	m_是否多线程.m_私有 = true;

	m_时间区间 = f_alloc_uVec2Prop(nullptr, L"时间区间");
	m_时间区间.m_私有 = true;
	f_prop_uVec2(m_时间区间) = { 0, 256 };

	m_是否缓存 = f_alloc_BoolProp(nullptr, L"是否缓存");
	m_是否缓存.m_私有 = true;
	f_prop_Bool(m_是否缓存) = false;

	m_缓存路径 = f_alloc_PathProp(nullptr, L"缓存路径");
	m_缓存路径.m_私有 = true;

	m_文件名 = f_alloc_StrProp(nullptr, L"文件名称");
	m_文件名.m_私有 = true;

	m_重置时间 = f_alloc_UI32Prop(nullptr, L"重置时间", 0);
	m_重置时间.m_私有 = true;
	f_prop_UI32(m_重置时间) = 0;

	m_视口互交 = f_alloc_BoolProp(nullptr, L"视口互交");
	m_视口互交.m_私有 = true;
	f_prop_Bool(m_视口互交) = false;
}

C_解算器更新节点::~C_解算器更新节点() {
	f_NodeCtx_get默认场景()->f_remove物体(m_数据可视物体, E_场景物体容器类型::e_集合);
	f_NodeCtx_get默认场景()->f_remove物体(m_飞溅可视物体, E_场景物体容器类型::e_集合);
	f_NodeCtx_get默认场景()->f_remove物体(m_肌腱可视物体, E_场景物体容器类型::e_集合);
}

bool C_解算器更新节点::f_update() {
	auto* mesh = f_ob_fromMesh(m_数据可视物体);
	auto* mesh飞溅 = f_ob_fromMesh(m_飞溅可视物体);

	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		mesh->f_Clear();
		mesh飞溅->f_Clear();

		return m_是否完成计算;
	}
	
	if (m_子集节点树->g_节点是否可编辑) {
		m_子集节点树->g_节点是否可编辑;
	}
	f_get输出插座(1)->f_setData(m_Physics);

	
	float32 帧时间 = DEF_F32插座数据(f_get输入插座(2));
	

	auto& frame = f_NodeCtx_get帧();
	m_Physics->m_步进ID = f_prop_UI32(frame.当前帧);

	//if (m_是否完成计算 == 2) {
	S_域区& dom = *f_Phy_get域属性(m_Physics);

	switch (m_Physics->m_IdType) {
	case E_物理引擎::E_物理引擎_Mujoco: {
		if (m_Physics->m_步进ID == f_prop_UI32(m_重置时间)) {
			f_phy_重置(m_Physics);
		}
		else {
			f_phy_步进解算(m_Physics);
		}

		uint32 肌腱数量 = f_phy_get肌腱数量(m_Physics);
		f_ob_set数据槽数量(m_肌腱可视物体, 肌腱数量);
		for (uint32 i = 0; i < 肌腱数量; ++i) {
			S_Mesh* mesh = f_ob_Mesh(m_肌腱可视物体, i);
			if (mesh == nullptr) {
				mesh = f_surface_创建网格对象(m_Ctx, E_网格数据枚举::e_Mesh_VULKAN);
				mesh->m_线宽 = 3;
				f_ob_set数据(m_肌腱可视物体, mesh, i);
				f_ob_set材质(m_肌腱可视物体, f_NodeCtx_get逐顶点连续线材质(), i);
			}
		}

		f_phy_构建肌腱物体可视(m_Physics, m_肌腱可视物体);
		break;
	}

	case E_物理引擎::E_物理引擎_FleX: {
		S_NvFleX* flex = static_cast<S_NvFleX*>(m_Physics);
		return f_update_FleX(m_Physics);

		if (flex->m_步进ID == 0) {
			mesh->f_Clear();
			mesh飞溅->f_Clear();
		}

		break;
	}
	case E_物理引擎::E_物理引擎_PBF: {
		f_ob_set材质(m_数据可视物体, gPBF调试材质, 0);
		m_数据可视物体->m_isUpdate = true;


		uint64 num = f_Phy_get粒子数量(m_Physics);
		if (num) {
			mesh->f_填充顶点数据(sizeof(vec4), num, nullptr);

			//E_序列map v = mesh->f_map顶点();
			//f_Phy_取流体调试数据(m_Physics, v.point);
			//mesh->f_unmap顶点();


			//f_Phy_取体素调试数据(m_Physics, m_体素顶点);
			if (m_显示域体素 && m_体素顶点.size()) {
				auto* 体素网格 = f_ob_fromMesh(m_数据可视物体, 1);
				体素网格->f_填充顶点数据(sizeof(vec4), m_体素顶点.size(), m_体素顶点.data());
				//域可视物体材质设置
				gPBF体素可视->f_域绘制参数(dom.m_单元属性);
			}
		}

	} break;


	case E_物理引擎::E_物理引擎_FLIP: {
		f_ob_set材质(m_数据可视物体, gFLIP调试材质, 0);


		//const uint32 域分辨率 = dom.m_单元属性.m_分辨率.x;
		f_ob_set域(m_数据可视物体, dom.m_单元属性, 0);

		if (m_上一次可视数据分辨率 != dom.m_单元属性.m_分辨率.x) {
			mesh->f_填充顶点数据(sizeof(vec4) + sizeof(float32), dom.m_单元属性.m_分辨率.x * dom.m_单元属性.m_分辨率.x * dom.m_单元属性.m_分辨率.x, nullptr);

			m_上一次可视数据分辨率 = dom.m_单元属性.m_分辨率.x;
		}

		if (dom.m_单元属性.m_分辨率.x) {
			//E_序列map v = mesh->f_map顶点();
			//填充GPU可视数据
			//f_Phy_取流体调试数据(m_Physics, (S_FLIP可视数据*)v.point);

			//mesh->f_unmap顶点();
		}

	} break;

	case E_物理引擎::E_物理引擎_Bullet: {

		break;
	}
	}


	

	

	m_是否完成计算 = 0;
	return false;
	
}

void C_解算器更新节点::f_异步解算() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		auto p = f_get输入插座(1)->f_get属性数据(E_值类型::e_插座Type_物理解算器);
		if (p.size()) {
			m_Physics = (S_Physics*)(p[0]);
		}
		return;
	}


	
	if (m_Physics->m_是否初始化) {
		m_Physics->m_是否初始化 = false;
		m_缓存保存帧 = 0;
		m_Physics->f_重置所有();
		m_是否完成计算 = 0;
		return;
	}
	else {
		ivec2 区间 = f_prop_iVec2(m_时间区间);
		if (m_Physics->m_步进ID > 区间.y || m_Physics->m_步进ID <= 区间.x) {
			m_Physics->f_重置();
		}
	}

	

	m_Physics->f_Update();
	switch (m_Physics->m_IdType)
	{
	case E_物理引擎::E_物理引擎_FleX: {
		auto flex = ((S_NvFleX*)m_Physics);

		std::vector<vec4> 体素顶点;
		if (m_显示域体素) {
			if (((S_NvFleX*)m_Physics)->m_解算参数.m_粒子数量) {
				f_NvFleX_取更新数据(m_Physics->f_getID(), 体素顶点);
				m_体素顶点 = 体素顶点;

				f_NvFleX_取飞溅数据(m_Physics->f_getID(), 体素顶点, 体素顶点);
				m_飞溅顶点 = 体素顶点;
			}
			else {
				m_体素顶点.clear();
				m_飞溅顶点.clear();
			}

			//f_uodate_FleX调试物体(m_体素顶点, m_飞溅顶点);
		}


		if (f_prop_Bool(m_是否缓存)) {
			std::string 保存路径 = f_get异步时间缓存路径(m_Physics, m_缓存保存帧);
			std::cout << "保存路径=" << 保存路径 << std::endl;
			FILE* f = fopen(保存路径.c_str(), "wb");
			if (f) {
				std::vector<vec4>	point;
				std::vector<vec4>	飞溅;
				std::vector<vec3>	速度;
				std::vector<int32>	激活;
				f_NvFleX_get数据(m_Physics->f_getID(), point, 飞溅, 速度, 激活);

				fwrite(&(m_Physics->m_Key), sizeof(uint64), 1, f);
				f_写入文件(f, point);
				f_写入文件(f, 飞溅);
				f_写入文件(f, 速度);
				f_写入文件(f, 激活);
				
				fclose(f);
			}
		}


		break;
	}
	default:
		//f_Phy_取体素调试数据(m_Physics, 体素顶点);
		break;
	}

	

	m_是否完成计算 = 2;
	m_Physics->m_步进时间 += 1.0;
	
}

void C_解算器更新节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_重置时间, f);
	f_prop_Load(m_粒子是否可视, f);
	f_prop_Load(m_是否多线程, f);
	f_prop_Load(m_时间区间, f);
	
	f_prop_Load(m_是否缓存, f);
	f_prop_Load(m_缓存路径, f);
	f_prop_Load(m_文件名, f);

	f_prop_Load(m_视口互交, f);
}

void C_解算器更新节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	f_prop_Save(m_重置时间, f);
	f_prop_Save(m_粒子是否可视, f);
	f_prop_Save(m_是否多线程, f);
	f_prop_Save(m_时间区间, f);
	
	f_prop_Save(m_是否缓存, f);
	f_prop_Save(m_缓存路径, f);
	f_prop_Save(m_文件名, f);

	f_prop_Save(m_视口互交, f);
}

/*S_插座增减方式 C_解算器更新节点::f_动态添加插座(E_插座方向 方向) {
	C_插座基类* socket;

	E_数据赋值方式 插座操作方式;

	uint16 num = f_get输入插座Num();
	if (num >= 4 && f_get输入插座(num - 2)->f_isLink() == false) {
		return { nullptr, E_数据赋值方式::e_赋值_None };
	}


	switch (方向)
	{
	case e_插座Type_输入: {
		DEF_创建引用插座_I(L"功能");

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	case e_插座Type_输出: {

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	default:
		return { nullptr, E_数据赋值方式::e_赋值_None };
	}

	f_set是否要更新(true);
	return { socket, 插座操作方式 };
}*/

std::string C_解算器更新节点::f_get缓存路径(S_Physics* Physics) {
	ivec2 区间 = f_prop_iVec2(m_时间区间);

	if (Physics->m_步进ID > 区间.y || Physics->m_步进ID < 区间.x) {
		return "";
	}
	std::string 编号 = f_整数值转字符串(int32(Physics->m_步进ID));
	
	auto path = f_prop_Path(m_缓存路径) / f_prop_Path(m_文件名);
	std::string 保存路径 = path.string();
	保存路径 += "_" + 编号 + ".bpfcache";

	return 保存路径;
}

std::string C_解算器更新节点::f_get异步时间缓存路径(S_Physics* Physics, int32 缓存帧) {
	ivec2 区间 = f_prop_iVec2(m_时间区间);

	if (缓存帧 > 区间.y || 缓存帧 < 区间.x) {
		return "";
	}
	std::string 编号 = f_整数值转字符串(缓存帧);

	auto path = f_prop_Path(m_缓存路径) / f_prop_Path(m_文件名);
	std::string 保存路径 = path.string();
	保存路径 += "_" + 编号 + ".bpfcache";

	return 保存路径;
}

bool C_解算器更新节点::f_update_FleX(S_Physics* Physics) {
	
	auto flex = ((S_NvFleX*)Physics);

	if (f_get输入插座(2)->f_isLink()) {
		Physics->m_步进ID = int32(DEF_F32插座数据(f_get输入插座(2)));
	}
	else {
		S_时间帧& 帧 = f_NodeCtx_get帧();
		Physics->m_步进ID = f_prop_I32(帧.当前帧);
	}
	
	




	if (f_prop_Bool(S_NodeCtx_模拟计算::g_是否开启解算)) {
		To_解算物理:
		if (m_是否完成计算 == 0) {
			if (f_prop_Bool(m_是否多线程)) {
				m_是否完成计算 = 1;
				m_缓存保存帧 = Physics->m_步进ID;
				bool 是否更新 = f_NodeCtx_物理模拟线程入栈(this);
				return true;
			}
			else {
				f_异步解算();
				goto To_更新显示;
			}
		}
		else if (m_是否完成计算 == 2) {
		To_更新显示:
			f_uodate_FleX调试物体(m_体素顶点, m_飞溅顶点);
			
			if (flex->m_刚体.size()) {
				std::vector<vec4> rot;
				std::vector<vec3> loc;
				f_NvFleX_取变换数据(flex->m_NvFleX_Key, rot, loc);
				flex->f_更新物体刚体变换(rot, loc);
			}

			m_是否完成计算 = 0;
		}
		else {
			return true;
		}
	}
	else {
		if (Physics->m_是否初始化) {
			goto To_解算物理;
		}
		std::string 保存路径 = f_get缓存路径(Physics);

		if (f_file_文件是否存在(保存路径) && !m_是否完成计算) {
			FILE* f = fopen(保存路径.c_str(), "rb");
			if (f) {
				std::vector<vec4>	point;
				std::vector<vec4>	飞溅;
				std::vector<vec3>	速度;
				std::vector<int32>	激活;

				uint64 记录物理体状态 = 0;
				fread(&记录物理体状态, sizeof(uint64), 1, f);
				if (记录物理体状态 == Physics->m_Key) {
					f_读取文件(f, &point);
					f_读取文件(f, &飞溅);
					f_读取文件(f, &速度);
					f_读取文件(f, &激活);

					fclose(f);
				}
				else {
					fclose(f);
					goto To_解算物理;
				}

				f_uodate_FleX调试物体(point, 飞溅);

			}
		}
		
		else {
			goto To_解算物理;
			return true;
		}

	}
	
	return false;
}

bool C_解算器更新节点::f_uodate_FleX调试物体(std::vector<vec4>& 流体粒子, std::vector<vec4>& 飞溅粒子) {
	uint64 num = 流体粒子.size();
	if (num) {
		auto* mesh流体 = f_ob_fromMesh(m_数据可视物体);
		
		vec4* sv = 流体粒子.data();

		f_ob_set材质(m_数据可视物体, gPBF调试材质, 0);
		m_数据可视物体->m_isUpdate = true;

		mesh流体->f_填充顶点数据(sizeof(vec4), num, nullptr);
		/*E_序列map v = mesh流体->f_map顶点();
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			((vec4*)v.point)[i] = sv[i];
		}
		mesh流体->f_unmap顶点();*/
	}

	num = 飞溅粒子.size();
	if (num) {
		auto* mesh飞溅 = f_ob_fromMesh(m_飞溅可视物体);

		vec4* sv = 飞溅粒子.data();

		//f_ob_set材质(m_飞溅可视物体, gPBF调试材质, 0);
		mesh飞溅->f_填充顶点数据(sizeof(vec4), num, nullptr);
		/*E_序列map v = mesh飞溅->f_map顶点();
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			((vec4*)v.point)[i] = sv[i];
		}
		mesh飞溅->f_unmap顶点();*/
	}
	return false;
}

C_节点基类* f_node_加载解算器更新节点(S_设备环境& ctx, FILE* f) {
	C_解算器更新节点* node = new C_解算器更新节点(ctx);
	return node;
}

void f_node_保存解算器更新节点(C_节点基类* n, FILE* f) {

}
























C_解算器添加物体节点::C_解算器添加物体节点(S_设备环境& ctx) : C_节点基类("解算器添加物体节点") {
	m_Name = L"解算器添加物体";

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");

	DEF_创建物体_Array1D插座_I(L"物理体");
}

C_解算器添加物体节点::~C_解算器添加物体节点() {

}

bool C_解算器添加物体节点::f_update() {
	return false;
}

void C_解算器添加物体节点::f_异步解算() {

}

C_节点基类* f_node_加载解算器添加物体节点(S_设备环境& ctx, FILE* f) {
	C_解算器添加物体节点* node = new C_解算器添加物体节点(ctx);
	return node;
}






C_应用力节点::C_应用力节点(S_设备环境& ctx) : C_节点基类(DEF_应用力节点) {
	m_更新方式 = E_节点更新方式::e_节点更新_实时;
	m_Name = L"应用力";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建Vec3_Array1D插座_I(L"力方向");
	DEF_创建F32_Array1D插座_I(L"力强度");

	DEF_创建物理引擎插座_O(L"物理引擎");


	m_视口互交 = f_alloc_BoolProp(nullptr, L"视口互交");
	m_视口互交.m_私有 = true;
	f_prop_Bool(m_视口互交) = false;
}

C_应用力节点::~C_应用力节点() {

}

bool C_应用力节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	auto& 力方向 = *DEF_Vec3_Array1D插座数据(f_get输入插座(2), 0);
	auto& 力强度 = *DEF_F32_Array1D插座数据(f_get输入插座(2), 0);

	if (f_prop_Bool(S_节点数据::g_物理引擎视口互交) && S_节点数据::g_当前操作视口相机) {

		vec3 ray[2];
		auto mat = f_mat4_左手转右手坐标系(f_mat44_identity());
		ray[0] = mat * S_节点数据::g_视口鼠标点射线[0];
		ray[1] = vec_normalize(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]);
		
		float32 dis = 1e+7;
		auto scene = f_NodeCtx_get默认场景();
		//auto obs = f_scene_射线拾取(scene, mat * S_节点数据::g_视口鼠标点射线[0], mat * S_节点数据::g_视口鼠标点射线[1], &dis);

		//if (obs.size()) {
		//	ray[0] = mat * (S_节点数据::g_视口鼠标点射线[0] + ray[1] * dis);
		//	std::cout << "是否拾取 = " << ray[0].x << " : " << ray[0].y << std::endl;
		//}
		if (S_节点数据::g_视口物理互交参数.bodyID >= 0) {
			auto 拾取坐标参数 = S_节点数据::g_视口物理互交参数;
			拾取坐标参数.pos = mat * 拾取坐标参数.pos;
			拾取坐标参数.vec = mat * 拾取坐标参数.vec;
			f_Phy_应用力(m_Physics, S_节点数据::g_视口物理互交参数);

			std::cout << "移动长度A = " << " x:" << 拾取坐标参数.vec.x << " y:" << 拾取坐标参数.vec.y << " z:" << 拾取坐标参数.vec.z << std::endl;
		}
		
	}

	f_get输出插座(1)->f_setData(m_Physics);
	return false;
}

void C_应用力节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_视口互交, f);
}

void C_应用力节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_视口互交, f);
}

C_节点基类* f_node_加载应用力节点(S_设备环境& ctx, FILE* f) {
	C_应用力节点* node = new C_应用力节点(ctx);
	return node;
}

void f_node_保存应用力节点(C_节点基类* n, FILE* f) {
	C_应用力节点* node = static_cast<C_应用力节点*>(n);
}





C_PBF更新邻接信息节点::C_PBF更新邻接信息节点(S_设备环境& ctx) : C_节点基类("PBF更新邻接信息节点")
{
}

C_PBF更新邻接信息节点::~C_PBF更新邻接信息节点()
{
}

bool C_PBF更新邻接信息节点::f_update()
{
	return false;
}







C_FleX参数节点::C_FleX参数节点(S_设备环境& ctx) : C_节点基类("FleX参数节点")
{
	m_Name = L"FleX参数";

	C_插座基类* socket;
	//1
	DEF_创建物理引擎插座_I(L"物理引擎");

	//2
	DEF_创建F32插座_v1_I(L"时间步进");
	//3
	DEF_创建Vec3插座_v1_I(L"重力");
	//4
	DEF_创建F32插座_v1_I(L"粒子半径");
	//5
	DEF_创建物体插座_I(L"域");
	

	DEF_F32插座数据(f_get输入插座(2)) = 1.0f / 60.0f;
	DEF_Vec3插座数据(f_get输入插座(3)) = { 0.0f, -9.8f,0.0f };
	DEF_F32插座数据(f_get输入插座(4)) = 0.1;
	


	m_迭代次数 = f_alloc_UI32Prop(nullptr, L"迭代次数");
	m_迭代次数.m_私有 = true;
	f_prop_UI32(m_迭代次数) = 3;
	//13 solidRestDistance
	//DEF_创建F32插座_I(L"固体重置距离");
	m_固体重置距离 = f_alloc_F32Prop(nullptr, L"固体重置距离");
	m_固体重置距离.m_私有 = true;
	f_prop_F32(m_固体重置距离) = 0.0;
	
	//14 fluidRestDistance
	//DEF_创建F32插座_I(L"流体重置距离");
	m_流体重置距离 = f_alloc_F32Prop(nullptr, L"流体重置距离");
	m_流体重置距离.m_私有 = true;
	f_prop_F32(m_流体重置距离) = 0.1*0.55;


	//11
	//DEF_创建Vec3插座_I(L"风向");
	m_风向 = f_alloc_Vec3Prop(nullptr, L"风向");
	m_风向.m_私有 = true;
	f_prop_Vec3(m_风向) = { 0,0,0 };
	//11
	//DEF_创建F32插座_I(L"布料拖拽");
	m_布料拖拽 = f_alloc_F32Prop(nullptr, L"布料拖拽");
	m_布料拖拽.m_私有 = true;
	f_prop_F32(m_布料拖拽) = 0.0;
	//12
	//DEF_创建F32插座_I(L"空气阻力");
	m_空气阻力 = f_alloc_F32Prop(nullptr, L"空气阻力");
	m_空气阻力.m_私有 = true;
	f_prop_F32(m_空气阻力) = 0.0;


	
	//4 dynamicFriction
	//DEF_创建F32插座_I(L"动态摩擦");
	m_动态摩擦 = f_alloc_F32Prop(nullptr, L"动态摩擦");
	m_动态摩擦.m_私有 = true;
	f_prop_F32(m_动态摩擦) = 0.01;
	//5 staticFriction
	//DEF_创建F32插座_I(L"静态摩擦");
	m_静态摩擦 = f_alloc_F32Prop(nullptr, L"静态摩擦");
	m_静态摩擦.m_私有 = true;
	f_prop_F32(m_静态摩擦) = 0.0;
	//6 particleFriction
	//DEF_创建F32插座_I(L"粒子摩擦");
	m_粒子摩擦 = f_alloc_F32Prop(nullptr, L"粒子摩擦");
	m_粒子摩擦.m_私有 = true;
	f_prop_F32(m_粒子摩擦) = 0.0;
	//6 restitution
	//DEF_创建F32插座_I(L"形态碰撞重置");
	m_碰撞重置 = f_alloc_F32Prop(nullptr, L"碰撞重置");
	m_碰撞重置.m_私有 = true;
	f_prop_F32(m_碰撞重置) = 0.0;
	//8 adhesion
	//DEF_创建F32插座_I(L"附着力");
	m_附着力 = f_alloc_F32Prop(nullptr, L"附着力");
	m_附着力.m_私有 = true;
	f_prop_F32(m_附着力) = 0.0;
	//8 sleepThreshold
	//DEF_创建F32插座_I(L"休眠");
	m_休眠 = f_alloc_F32Prop(nullptr, L"休眠");
	m_休眠.m_私有 = true;
	f_prop_F32(m_休眠) = 0.0;
	//7 maxSpeed
	//DEF_创建F32插座_I(L"最大速度");
	m_最大速度 = f_alloc_F32Prop(nullptr, L"最大速度");
	m_最大速度.m_私有 = true;
	f_prop_F32(m_最大速度) = 1000.0;
	//7 maxAcceleration
	//DEF_创建F32插座_I(L"最大加速");
	m_最大加速 = f_alloc_F32Prop(nullptr, L"最大加速");
	m_最大加速.m_私有 = true;
	f_prop_F32(m_最大加速) = 100.0;
	//7 shockPropagation
	//DEF_创建F32插座_I(L"传播收敛");
	m_传播收敛 = f_alloc_F32Prop(nullptr, L"传播收敛");
	m_传播收敛.m_私有 = true;
	f_prop_F32(m_传播收敛) = 0.0;
	//7 dissipation
	//DEF_创建F32插座_I(L"消散");
	m_消散 = f_alloc_F32Prop(nullptr, L"消散");
	m_消散.m_私有 = true;
	f_prop_F32(m_消散) = 0.0;
	//7 damping
	//DEF_创建F32插座_I(L"阻力");
	m_阻力 = f_alloc_F32Prop(nullptr, L"阻力");
	m_阻力.m_私有 = true;
	f_prop_F32(m_阻力) = 0.0;



	//8 cohesion
	//DEF_创建F32插座_I(L"凝聚性");
	m_凝聚性 = f_alloc_F32Prop(nullptr, L"凝聚性");
	m_凝聚性.m_私有 = true;
	f_prop_F32(m_凝聚性) = 0.025;
	//8 surfaceTension
	//DEF_创建F32插座_I(L"表面张力");
	m_表面张力 = f_alloc_F32Prop(nullptr, L"表面张力");
	m_表面张力.m_私有 = true;
	f_prop_F32(m_表面张力) = 0.0;
	//9 viscosity
	//DEF_创建F32插座_I(L"粘度");
	m_粘度 = f_alloc_F32Prop(nullptr, L"粘度");
	m_粘度.m_私有 = true;
	f_prop_F32(m_粘度) = 2.0;
	//9 vorticityConfinement
	//DEF_创建F32插座_I(L"涡流");
	m_涡流 = f_alloc_F32Prop(nullptr, L"涡流");
	m_涡流.m_私有 = true;
	f_prop_F32(m_涡流) = 30.0;
	//9 anisotropyScale
	//DEF_创建F32插座_I(L"流体球拉伸大小");
	m_流体球拉伸大小 = f_alloc_F32Prop(nullptr, L"流体球拉伸大小");
	m_流体球拉伸大小.m_私有 = true;
	f_prop_F32(m_流体球拉伸大小) = 1.0;
	//9 anisotropyMin
	//DEF_创建F32插座_I(L"流体球拉伸最小");
	m_流体球拉伸最小 = f_alloc_F32Prop(nullptr, L"流体球拉伸最小");
	m_流体球拉伸最小.m_私有 = true;
	f_prop_F32(m_流体球拉伸最小) = 0.1;
	//9 anisotropyMax
	//DEF_创建F32插座_I(L"流体球拉伸最大");
	m_流体球拉伸最大 = f_alloc_F32Prop(nullptr, L"流体球拉伸最大");
	m_流体球拉伸最大.m_私有 = true;
	f_prop_F32(m_流体球拉伸最大) = 2.0;
	//9 smoothing
	//DEF_创建F32插座_I(L"平滑强度");
	m_平滑强度 = f_alloc_F32Prop(nullptr, L"平滑强度");
	m_平滑强度.m_私有 = true;
	f_prop_F32(m_平滑强度) = 1.0;
	//9 solidPressure
	//DEF_创建F32插座_I(L"固体压力");
	m_固体压力 = f_alloc_F32Prop(nullptr, L"固体压力");
	m_固体压力.m_私有 = true;
	f_prop_F32(m_固体压力) = 0.0;
	//9 freeSurfaceDrag
	//DEF_创建F32插座_I(L"边界阻力");
	m_边界阻力 = f_alloc_F32Prop(nullptr, L"边界阻力");
	m_边界阻力.m_私有 = true;
	f_prop_F32(m_边界阻力) = 0.0;
	//10 buoyancy
	//DEF_创建F32插座_I(L"浮力");
	m_浮力 = f_alloc_F32Prop(nullptr, L"浮力");
	m_浮力.m_私有 = true;
	f_prop_F32(m_浮力) = 1.0;



	//10 diffuseThreshold
	//DEF_创建F32插座_I(L"飞溅产生");
	m_飞溅产生 = f_alloc_F32Prop(nullptr, L"飞溅产生");
	m_飞溅产生.m_私有 = true;
	f_prop_F32(m_飞溅产生) = 100.0;
	//10 diffuseBuoyancy
	//DEF_创建F32插座_I(L"飞溅浮力");
	m_飞溅浮力 = f_alloc_F32Prop(nullptr, L"飞溅浮力");
	m_飞溅浮力.m_私有 = true;
	f_prop_F32(m_飞溅浮力) = 1.0;
	//10 diffuseDrag
	//DEF_创建F32插座_I(L"飞溅阻力");
	m_飞溅阻力 = f_alloc_F32Prop(nullptr, L"飞溅阻力");
	m_飞溅阻力.m_私有 = true;
	f_prop_F32(m_飞溅阻力) = 0.8;
	//10 diffuseBallistic
	//DEF_创建F32插座_I(L"飞溅发射");
	m_飞溅发射 = f_alloc_UI32Prop(nullptr, L"飞溅发射");
	m_飞溅发射.m_私有 = true;
	f_prop_UI32(m_飞溅发射) = 16;
	//10 diffuseLifetime
	//DEF_创建F32插座_I(L"飞溅寿命");
	m_飞溅寿命 = f_alloc_F32Prop(nullptr, L"飞溅寿命");
	m_飞溅寿命.m_私有 = true;
	f_prop_F32(m_飞溅寿命) = 2.0;


	//7 collisionDistance
	//DEF_创建F32插座_I(L"碰撞距离");
	m_碰撞距离 = f_alloc_F32Prop(nullptr, L"碰撞距离");
	m_碰撞距离.m_私有 = true;
	f_prop_F32(m_碰撞距离) = 0.01;
	//7 particleCollisionMargin
	//DEF_创建F32插座_I(L"碰撞距离边缘");
	m_碰撞距离边缘 = f_alloc_F32Prop(nullptr, L"碰撞距离边缘");
	m_碰撞距离边缘.m_私有 = true;
	f_prop_F32(m_碰撞距离边缘) = 0.0;
	//7 particleCollisionMargin
	//DEF_创建F32插座_I(L"碰撞形状边缘");
	m_碰撞形状边缘 = f_alloc_F32Prop(nullptr, L"碰撞形状边缘");
	m_碰撞形状边缘.m_私有 = true;
	f_prop_F32(m_碰撞形状边缘) = 0.0;



	m_松弛 = f_alloc_F32Prop(nullptr, L"松弛");
	m_松弛.m_私有 = true;
	f_prop_F32(m_松弛) = 1.0;
	m_松弛模式 = f_alloc_EnumProp(nullptr, { {L"全局", ""}, {L"局部", ""} }, L"松弛方式");
	m_松弛模式.m_私有 = true;
	f_prop_enum(m_松弛模式) = 1;
	
	
	


	DEF_创建物理引擎插座_O(L"物理引擎");



}

C_FleX参数节点::~C_FleX参数节点()
{
}

bool C_FleX参数节点::f_update()
{
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		f_get输出插座(1)->f_setData((void*)nullptr);
		return false;
	}


	switch (m_Physics->m_IdType) {
	case E_物理引擎::E_物理引擎_FleX: {
		S_NvFleX* flex = static_cast<S_NvFleX*>(m_Physics);

		flex->m_解算参数.m_时间步进 = DEF_F32插座数据(f_get输入插座(2));
		flex->m_解算参数.gravity = DEF_Vec3插座数据(f_get输入插座(3));
		flex->m_解算参数.radius = DEF_F32插座数据(f_get输入插座(4));
		m_Physics->m_粒子半径 = flex->m_解算参数.radius;


		auto* 物体域 = DEF_物体插座数据(f_get输入插座(5), 0);
		S_Mesh* mesh = nullptr;
		if (物体域 && (mesh = f_ob_fromMesh(物体域)) ) {
			auto mat = f_ob_get实例变换矩阵(物体域, 0);
			S_Bounding 域 = f_surface_计算包围盒(mesh, &mat);
			flex->m_解算参数.planes[0] = 域.min;
			flex->m_解算参数.planes[1] = 域.max;
		}
		else {
			flex->m_解算参数.planes[0] = { -5,-5,-5 };
			flex->m_解算参数.planes[1] = { 5,5,5 };
		}
		


		flex->m_解算参数.solidRestDistance = f_prop_F32(m_固体重置距离);
		flex->m_解算参数.fluidRestDistance = f_prop_F32(m_流体重置距离);
		flex->m_解算参数.numIterations = f_prop_UI32(m_迭代次数);

		flex->m_解算参数.wind = f_prop_Vec3(m_风向);
		flex->m_解算参数.drag = f_prop_F32(m_布料拖拽);
		flex->m_解算参数.lift = f_prop_F32(m_空气阻力);

		flex->m_解算参数.dynamicFriction = f_prop_F32(m_动态摩擦);
		flex->m_解算参数.staticFriction = f_prop_F32(m_静态摩擦);
		flex->m_解算参数.particleFriction = f_prop_F32(m_粒子摩擦);
		flex->m_解算参数.restitution = f_prop_F32(m_碰撞重置);
		flex->m_解算参数.adhesion = f_prop_F32(m_附着力);
		flex->m_解算参数.sleepThreshold = f_prop_F32(m_休眠);
		flex->m_解算参数.maxSpeed = f_prop_F32(m_最大速度);
		flex->m_解算参数.maxAcceleration = f_prop_F32(m_最大加速);
		flex->m_解算参数.shockPropagation = f_prop_F32(m_传播收敛);
		flex->m_解算参数.dissipation = f_prop_F32(m_消散);
		flex->m_解算参数.damping = f_prop_F32(m_阻力);

		flex->m_解算参数.cohesion = f_prop_F32(m_凝聚性);
		flex->m_解算参数.surfaceTension = f_prop_F32(m_表面张力);
		flex->m_解算参数.viscosity = f_prop_F32(m_粘度);
		flex->m_解算参数.vorticityConfinement = f_prop_F32(m_涡流);
		flex->m_解算参数.anisotropyScale = f_prop_F32(m_流体球拉伸大小);
		flex->m_解算参数.anisotropyMin = f_prop_F32(m_流体球拉伸最小);
		flex->m_解算参数.anisotropyMax = f_prop_F32(m_流体球拉伸最大);
		flex->m_解算参数.smoothing = f_prop_F32(m_平滑强度);
		flex->m_解算参数.solidPressure = f_prop_F32(m_固体压力);
		flex->m_解算参数.freeSurfaceDrag = f_prop_F32(m_边界阻力);
		flex->m_解算参数.buoyancy = f_prop_F32(m_浮力);

		flex->m_解算参数.diffuseThreshold = f_prop_F32(m_飞溅产生);
		flex->m_解算参数.diffuseBuoyancy = f_prop_F32(m_飞溅浮力);
		flex->m_解算参数.diffuseDrag = f_prop_F32(m_飞溅阻力);
		flex->m_解算参数.diffuseBallistic = f_prop_F32(m_飞溅发射);
		flex->m_解算参数.diffuseLifetime = f_prop_F32(m_飞溅寿命);

		flex->m_解算参数.collisionDistance = f_prop_F32(m_碰撞距离);
		flex->m_解算参数.particleCollisionMargin = f_prop_F32(m_碰撞距离边缘);
		flex->m_解算参数.shapeCollisionMargin = f_prop_F32(m_碰撞形状边缘);

		flex->m_解算参数.diffuseLifetime = f_prop_F32(m_松弛);
		flex->m_解算参数.relaxationMode = E_FlexRelaxationMode(f_prop_enum(m_松弛模式));

		

		break;
	}
	}

	f_get输出插座(1)->f_setData(m_Physics);

	return false;
}

void C_FleX参数节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_迭代次数, f);
	f_prop_Load(m_固体重置距离, f);
	f_prop_Load(m_流体重置距离, f);
	f_prop_Load(m_风向, f);
	f_prop_Load(m_布料拖拽, f);
	f_prop_Load(m_空气阻力, f);
	f_prop_Load(m_动态摩擦, f);
	f_prop_Load(m_静态摩擦, f);
	f_prop_Load(m_粒子摩擦, f);
	f_prop_Load(m_碰撞重置, f);
	f_prop_Load(m_附着力, f);
	f_prop_Load(m_休眠, f);
	f_prop_Load(m_最大速度, f);
	f_prop_Load(m_最大加速, f);
	f_prop_Load(m_传播收敛, f);
	f_prop_Load(m_消散, f);
	f_prop_Load(m_阻力, f);
	f_prop_Load(m_凝聚性, f);
	f_prop_Load(m_表面张力, f);
	f_prop_Load(m_粘度, f);
	f_prop_Load(m_涡流, f);
	f_prop_Load(m_流体球拉伸大小, f);
	f_prop_Load(m_流体球拉伸最小, f);
	f_prop_Load(m_流体球拉伸最大, f);
	f_prop_Load(m_平滑强度, f);
	f_prop_Load(m_固体压力, f);
	f_prop_Load(m_边界阻力, f);
	f_prop_Load(m_浮力, f);
	f_prop_Load(m_飞溅产生, f);
	f_prop_Load(m_飞溅浮力, f);
	f_prop_Load(m_飞溅阻力, f);
	f_prop_Load(m_飞溅发射, f);
	f_prop_Load(m_飞溅寿命, f);
	f_prop_Load(m_碰撞距离, f);
	f_prop_Load(m_碰撞距离边缘, f);
	f_prop_Load(m_碰撞形状边缘, f);
	f_prop_Load(m_松弛, f);
	f_prop_Load(m_松弛模式, f);
}

void C_FleX参数节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	f_prop_Save(m_迭代次数, f);
	f_prop_Save(m_固体重置距离, f);
	f_prop_Save(m_流体重置距离, f);
	f_prop_Save(m_风向, f);
	f_prop_Save(m_布料拖拽, f);
	f_prop_Save(m_空气阻力, f);
	f_prop_Save(m_动态摩擦, f);
	f_prop_Save(m_静态摩擦, f);
	f_prop_Save(m_粒子摩擦, f);
	f_prop_Save(m_碰撞重置, f);
	f_prop_Save(m_附着力, f);
	f_prop_Save(m_休眠, f);
	f_prop_Save(m_最大速度, f);
	f_prop_Save(m_最大加速, f);
	f_prop_Save(m_传播收敛, f);
	f_prop_Save(m_消散, f);
	f_prop_Save(m_阻力, f);
	f_prop_Save(m_凝聚性, f);
	f_prop_Save(m_表面张力, f);
	f_prop_Save(m_粘度, f);
	f_prop_Save(m_涡流, f);
	f_prop_Save(m_流体球拉伸大小, f);
	f_prop_Save(m_流体球拉伸最小, f);
	f_prop_Save(m_流体球拉伸最大, f);
	f_prop_Save(m_平滑强度, f);
	f_prop_Save(m_固体压力, f);
	f_prop_Save(m_边界阻力, f);
	f_prop_Save(m_浮力, f);
	f_prop_Save(m_飞溅产生, f);
	f_prop_Save(m_飞溅浮力, f);
	f_prop_Save(m_飞溅阻力, f);
	f_prop_Save(m_飞溅发射, f);
	f_prop_Save(m_飞溅寿命, f);
	f_prop_Save(m_碰撞距离, f);
	f_prop_Save(m_碰撞距离边缘, f);
	f_prop_Save(m_碰撞形状边缘, f);
	f_prop_Save(m_松弛, f);
	f_prop_Save(m_松弛模式, f);
}

C_节点基类* f_node_加载FleX参数节点(S_设备环境& ctx, FILE* f) {
	C_FleX参数节点* node = new C_FleX参数节点(ctx);
	return node;
}

void f_node_保存FleX参数节点(C_节点基类* n, FILE* f) {

}




C_更新肌腱节点::C_更新肌腱节点(S_设备环境& ctx) : C_节点基类(DEF_更新肌腱节点) {
	m_Name = L"FleX参数";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建I32插座_I(L"ID", nullptr);
	DEF_创建F32插座_I(L"强度", nullptr);
	
	DEF_创建物理引擎插座_O(L"物理引擎");
	
}

C_更新肌腱节点::~C_更新肌腱节点() {
}

bool C_更新肌腱节点::f_update() {
	auto* physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	
	if (physics) {
		auto& ID = DEF_I32插座数据(f_get输入插座(2));
		auto& 强度 = DEF_F32插座数据(f_get输入插座(3), 0);

		f_phy_set肌腱力度(physics, &强度, ID);
	}
	
	f_get输出插座(1)->f_setData(physics);
	return false;
}

void C_更新肌腱节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_更新肌腱节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载更新肌腱节点(S_设备环境& ctx, FILE* f) {
	C_更新肌腱节点* node = new C_更新肌腱节点(ctx);
	return node;
}

void f_node_保存更新肌腱节点(C_节点基类* n, FILE* f) {
	C_更新肌腱节点* node = dynamic_cast<C_更新肌腱节点*>(n);
}





